﻿' ------------------------------------------------------------------------------
' A simple implementation of a few Assert predicates. A few reporting
' functions that display information in the Log window by calling
' Trace.WriteLine(). SQL reporting functions that report to the Log
' window and the SQL Inspector window. Error and exception reporting
' functions that show the error to the user.
' ------------------------------------------------------------------------------
' This file is part of the SQL Server 2008 Technology Demonstration. This
' application was designed and coded by Eric Weitzman, LandTime Inc, for
' Microsoft Corporation. Contact Ed Katibah at Microsoft about this demo.
' Copyright © 2008 Microsoft Corporation. All rights reserved.
' ------------------------------------------------------------------------------

Public Module ReportingUtils

    Private m_timer As DateTime?

    Public Sub Assert(ByVal val As Boolean, ByVal msg As String)
        If val Then Return
        If ReportErrorQuery("ASSERTION FAILED: " & msg) Then TerminateProgram()
    End Sub

    Public Sub AssertNotReached(ByVal msg As String)
        If ReportErrorQuery("ASSERT NOT REACHED FAILED: " & msg) Then TerminateProgram()
    End Sub

    Public Sub ReportError(ByVal msg As String)
        Trace.WriteLine("Error: " & msg)
    End Sub

    Public Sub ReportWebPageError(ByVal message As String, ByVal url As String, ByVal line As Integer)
        Trace.WriteLine("Error: webpage: " & url & " line: " & line)
        Trace.WriteLine("Error: message:  " & message)
    End Sub

    Public Sub StartTimer()
        m_timer = DateTime.Now
    End Sub

    Public Sub ShowTimer(Optional ByVal msg As String = "")
        If m_timer Is Nothing Then Return
        Dim sec As Double = Math.Round(CType(DateTime.Now - m_timer, TimeSpan).TotalSeconds, 2)
        If msg <> "" Then
            Trace.WriteLine("ELAPSED TIME: " & sec & ": " & msg)
        Else
            Trace.WriteLine("ELAPSED TIME: " & sec)
        End If
        Trace.Flush()
        m_timer = Nothing
    End Sub

    Public Sub ReportException(ByVal ex As Exception)
        Dim msg As String
        If TypeOf (ex) Is SqlException Then
            Dim sqlex As SqlException = CType(ex, SqlException)
            msg = "SqlException: number = " & sqlex.Number & ": " & sqlex.Message
        Else
            msg = "Exception: " & ex.Message
        End If
        If msg.Length < 80 Then
            Trace.WriteLine(msg)
        Else
            While msg.Length > 70
                Dim split As Integer = msg.IndexOf(" "c, 70)
                If split = -1 Then
                    Trace.WriteLine(msg)
                    msg = ""
                Else
                    Trace.WriteLine(msg.Substring(0, split))
                    msg = msg.Substring(split)
                End If
            End While
            If msg.Length <> 0 Then Trace.WriteLine(msg)
        End If
        For Each caller As String In ex.StackTrace.Split(vbCrLf.ToCharArray, System.StringSplitOptions.RemoveEmptyEntries)
            Trace.WriteLine(caller)
        Next
    End Sub

    Public Function ReportErrorQuery(ByVal ex As Exception) As Boolean
        ReportException(ex)
        Return ReportErrorQueryBase(ex.Message, "exception", ex.GetType.ToString())
    End Function

    Public Function ReportErrorQuery(ByVal msg As String) As Boolean
        ReportError(msg)
        Return ReportErrorQueryBase(msg, "error", "Error")
    End Function

    Private Function ReportErrorQueryBase(ByVal msg As String, ByVal errortype As String, ByVal caption As String) As Boolean
        Dim sb As New System.Text.StringBuilder
        sb.Append("The following ").Append(errortype).AppendLine(" occurred:")
        sb.AppendLine()
        sb.AppendLine(msg)
        sb.AppendLine()
        sb.AppendLine("Exit the application?")
        Return DialogResult.Yes _
               = MessageBox.Show(sb.ToString, caption, MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button2)
    End Function

    Public Sub ReportSqlEvent(ByVal e As SqlEventArgs)
        Select Case e.Type
            Case EnumSqlEvent.eCommand : ReportSqlCommand(e.Message, e.Command, e)
            Case EnumSqlEvent.eOperation : ReportSqlOperation(e.Name, e.Message, e)
            Case EnumSqlEvent.eOpenSqlFilestreamError : ReportOpenSqlFilestreamError(e.ErrorCode, e)
        End Select
    End Sub

    Public Sub ReportSqlCommand(ByVal msg As String, ByVal cmd As SqlCommand, Optional ByVal e As SqlEventArgs = Nothing)
        If e Is Nothing Then e = New SqlEventArgs(msg, cmd)
        g_sqlinspector.SqlEvent(e)
        Trace.WriteLine(vbTab & "SQL: " & msg & ": " & cmd.CommandText)
        For Each arg As SqlParameter In cmd.Parameters
            Trace.WriteLine(vbTab & vbTab & arg.ParameterName & vbTab & arg.Value.ToString)
        Next
        Trace.Flush()
    End Sub

    Public Sub ReportSqlOperation(ByVal name As String, ByVal msg As String, Optional ByVal e As SqlEventArgs = Nothing)
        If e Is Nothing Then e = New SqlEventArgs(name, msg)
        g_sqlinspector.SqlEvent(e)
        If msg = "" Then
            Trace.WriteLine(name)
        Else
            Trace.WriteLine(name & ": " & msg)
        End If
        Trace.Flush()
    End Sub

    Public Sub ReportOpenSqlFilestreamError(ByVal errcode As UInt32, Optional ByVal e As SqlEventArgs = Nothing)
        If e Is Nothing Then e = New SqlEventArgs(errcode)
        g_sqlinspector.SqlEvent(e)
        Dim msg As String = String.Format("OpenSqlFilestream() failed: {0} ({1:X})", GetLastErrorMessage(errcode), errcode)
        ReportError(msg)
        MessageBox.Show(msg, "Filestream Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Sub


End Module
